package com.patterns.design.security.web.security;

import java.text.SimpleDateFormat;
import java.util.Iterator;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.owasp.esapi.Encoder;
import org.owasp.esapi.Validator;
import org.owasp.esapi.errors.IntrusionException;
import org.owasp.esapi.errors.ValidationException;

public class SecureRequestWrapper extends HttpServletRequestWrapper{
	
	protected static final Log logger = LogFactory.getLog(SecureRequestWrapper.class);

	private Encoder encoder;
	private Validator validator;
    boolean sanitizeNoJavascriptFlag=false;
    boolean encodeForHtmlInFilterFlag=false;
    boolean validateForHtmlFlag=false;
    boolean validateBaseOnSufixInFilterFlag=false;
    
	public SecureRequestWrapper(HttpServletRequest request, 
								Encoder encoder,
								Validator validator, 
						        boolean sanitizeNoJavascriptFlag,
						        boolean encodeForHtmlInFilterFlag,
						        boolean validateForHtmlFlag,
						        boolean validateBaseOnSufixInFilterFlag) {
		super(request);
		this.encoder=encoder;
		this.validator=validator;
        this.sanitizeNoJavascriptFlag=sanitizeNoJavascriptFlag;
        this.encodeForHtmlInFilterFlag=encodeForHtmlInFilterFlag;
        this.validateForHtmlFlag=validateForHtmlFlag;
        this.validateBaseOnSufixInFilterFlag=validateBaseOnSufixInFilterFlag;
	}

	@Override
	public Map getParameterMap(){
		Map map=this.getParameterMap();
		Iterator iter=map.keySet().iterator();
		String key=null;
		String[] values=null;
		while(iter.hasNext()){
			key=(String)iter.next();
			values=(String[])map.get(key);
			for(int i=0; i<values.length;i++){
				values[i]=cleanXSS(key, values[i]);
			}
		}
		return map;
	}
	
	@Override
	public String[] getParameterValues( String name){
		String[] values=super.getParameterValues(name);
		if(values==null){
			return null;
		}
		int count=values.length;
		String[] encodedValues=new String[count];
		for(int i=0;i<count;i++){
			encodedValues[i]=cleanXSS(name, values[i]);
		}
		return encodedValues;
	}
	
	public String getParameter(String name){
		String value=super.getParameter(name);
		value=cleanXSS(name, value);
		return value;
	}
	
	public String cleanXSS(String key, String value){
		try {
			String newValue=value;
			if(encodeForHtmlInFilterFlag){
				newValue= encoder.encodeForHTML(newValue);
			}
			if(sanitizeNoJavascriptFlag){
				newValue= validator.getValidSafeHTML("key", newValue, 4000, true);
			}
			if(validateForHtmlFlag){
				newValue= validator.getValidInput("key", newValue,"SafeString", 4000, true);
			}
			if(validateBaseOnSufixInFilterFlag){
				if(newValue.endsWith("Int")){
					newValue= validator.getValidInteger(key, newValue, 0, 1000, true).toString();
				}
				if(newValue.endsWith("Date")){
					SimpleDateFormat format=new SimpleDateFormat();
					newValue= validator.getValidDate(key, newValue, format, true).toString();
				}
				if(newValue.endsWith("Card")){
					newValue= validator.getValidInput("key", newValue,"CreditCard", 4000, true);
				}
				if(newValue.endsWith("Flag")){
					newValue= validator.getValidInput("key", newValue,"CreditCard", 4000, true);
				}
				if(newValue.endsWith("Email")){
					newValue= validator.getValidInput("key", newValue,"Email", 4000, true);
				}
				if(newValue.endsWith("String")){
					//Other strategy => No html tag. 
					//Note if us => ANSI
					//Note if europe => UTF8  
				}
				if(newValue.endsWith("Html")){
					//Other strategy => No Javascript.
					newValue= validator.getValidInput("key", newValue,"SafeString", 4000, true);
				}
				if(newValue.endsWith("Code")){
					//Other strategy => No rules...
				}
			}
   			logger.info("newValue: "+newValue);
   			return newValue;
		} catch (ValidationException e) {
			e.printStackTrace();
		} catch (IntrusionException e) {
			e.printStackTrace();
		}
		return value;
	}
}